﻿namespace HutongGames.PlayMakerEditor
{
    using HutongGames.PlayMaker;
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Runtime.CompilerServices;
    using System.Runtime.InteropServices;
    using UnityEditor;
    using UnityEngine;
    using AddOn;

    [Serializable]
    public class FsmEditor
    {
        [CompilerGenerated]
        private static bool InspectorHasFocus__BackingField;
        private readonly HutongGames.PlayMakerEditor.ActionEditor actionEditor;
        private readonly FsmBuilder builder;
        private static string currentScene;
        [SerializeField]
        private FsmDebugger debugger;
        private readonly FsmEventManager eventManager;
        private static readonly List<PlayMakerFSM> fsmComponentList = new List<PlayMakerFSM>();
        private static readonly List<Fsm> fsmList = new List<Fsm>();
        private static readonly Dictionary<GameObject, PlayMakerFSM> FSMSelectedOnGameObjects = new Dictionary<GameObject, PlayMakerFSM>();
        private FsmSelection fsmSelection;
        private readonly FsmGraphView graphView;
        private UnityEditor.EditorApplication.HierarchyWindowItemCallback hiearchyItemCallback;
        private static bool initialized;
        private readonly InspectorPanel inspector;
        public const float InspectorPanelWidth = 350f;
        private static FsmEditor instance;
        private bool mouseDown;
        private bool mouseUp;
        private bool openReport;
        private bool playmodeChanged;
        private EditorApplication.CallbackFunction playmodeDelegate;
        [SerializeField]
        private readonly List<Fsm> recentlySelectedList = new List<Fsm>();
        private bool repaint;
        private bool repaintAll;
        private static bool resetKeyboard;
        private PlayMakerFSM selectedFsmComponent;
        private FsmUnit selectedFsmUnit;
        private FsmDevice selectedFsmDevice;
        private GameObject selectedGameObject;
        private FsmTemplate selectedTemplate;
        private static string sendWindowCommandEvent;
        private readonly HutongGames.PlayMakerEditor.StateInspector stateInspector;
        private readonly MainToolbar toolbar;
        private static int updateIsModifiedPrefabInstance;
        private readonly HutongGames.PlayMakerEditor.VariableManager variableManager;
        private static bool warnedAboutEditingWhileRunning;
        private EditorWindow window;

        public FsmEditor()
        {
            instance = this;
            this.builder = new FsmBuilder();
            this.actionEditor = new HutongGames.PlayMakerEditor.ActionEditor();
            this.stateInspector = new HutongGames.PlayMakerEditor.StateInspector();
            this.eventManager = new FsmEventManager();
            this.variableManager = new HutongGames.PlayMakerEditor.VariableManager();
            this.graphView = new FsmGraphView();
            this.inspector = new InspectorPanel();
            this.toolbar = new MainToolbar();
            this.debugger = FsmDebugger.Instance;
        }

        public static void ShowSys()
        {
            UnityEditor.Selection.activeGameObject = FsmSys.Instance().gameObject;
            GraphView.viewLevel = FsmGraphView.GraphViewLevel.Sys;
        }

        public static bool IsSelectedSys()
        {
            return UnityEditor.Selection.activeGameObject == FsmSys.Instance().gameObject;
        }

        public static void AddDevice()
        {
            GameObject go = UnityEditor.Selection.activeGameObject;
            if (go != null)
            {
                if (go.GetComponentInChildren<FsmDevice>() == null)
                {
                    FsmDevice dev = go.AddComponent<FsmDevice>();
                    instance.OnSelectionChange();
                    FsmSys.RebuildDeviceList();
                }
                else
                {
                    Debug.LogError("本节点或子节点已经有FsmDevice组件");
                }
            }
        }

        public static void AddUnit()
        {
            GameObject go = UnityEditor.Selection.activeGameObject;
            if (go != null)
            {
                if (go.GetComponent<FsmUnit>() == null)
                {
                    FsmUnit unit = go.AddComponent<FsmUnit>();
                    instance.OnSelectionChange();
                    FsmDevice dev = unit.GetComponent<FsmDevice>();
                    if (dev != null)
                    {
                        dev.RebuildUnits();
                    }
                    else
                    {
                        Transform p = unit.transform.parent;
                        if (p != null && p.GetComponent<FsmDevice>() != null)
                            p.GetComponent<FsmDevice>().RebuildUnits();
                    }
                }
                else
                {
                    Debug.LogError("节点已经有FsmUnit组件");
                }
            }
        }

        public static void AddFsm()
        {
            AddFsmComponent();
        }

        public static void AddFsmComponent()
        {
            RegisterUndo("Add FSM Component");
            Window.SendEvent(EditorGUIUtility.CommandEvent("AddFsmComponent"));
        }

        public static void AutoAddPlayMakerGUI()
        {
            if (!Application.isPlaying && !(UnityEngine.Object.FindObjectOfType(typeof(PlayMakerGUI)) is PlayMakerGUI))
            {
                PlayMakerGUI.Instance.enabled = true;
                Debug.Log("Auto Added PlayMakerGUI to scene. Note, you need a PlayMakerGUI in the scene to see Playmaker Gizmos, OnGUI actions and iTween path editing. You can turn this option off in Preferences.");
            }
        }

        private static void CheckIsModifiedPrefabInstance()
        {
            updateIsModifiedPrefabInstance = 3;
        }

        private static void CheckReloadActions(FsmState state)
        {
            if (state.Actions.Length != state.ActionData.ActionCount)
            {
                state.LoadActions();
                if (FsmEditorSettings.EnableRealtimeErrorChecker)
                {
                    FsmErrorChecker.CheckFsmForErrors(state.Fsm);
                }
            }
        }

        public static void Copy()
        {
            if (InspectorHasFocus && (Inspector.Mode == HutongGames.PlayMakerEditor.InspectorMode.StateInspector))
            {
                HutongGames.PlayMakerEditor.StateInspector.CopySelectedActions();
            }
            else
            {
                EditorCommands.CopyStateSelection();
            }
        }

        public static void EditingActions()
        {
            if (instance != null)
            {
                StateInspector.EditingActions();
            }
        }

        public static bool FsmContainsState(Fsm fsm, FsmState state)
        {
            if ((fsm != null) && (state != null))
            {
                foreach (FsmState state2 in fsm.States)
                {
                    if (state2 == state)
                    {
                        return true;
                    }
                }
            }
            return false;
        }

        public static bool FsmListContainsFsm(Fsm fsm)
        {
            if (fsm != null)
            {
                foreach (Fsm fsm2 in FsmList)
                {
                    if (fsm2 == fsm)
                    {
                        return true;
                    }
                }
            }
            return false;
        }

        public static void GotoBreakpoint()
        {
            if (Fsm.BreakAtFsm != null)
            {
                SelectFsm(Fsm.BreakAtFsm);
                SelectState(Fsm.BreakAtState, true);
            }
        }

        private void HierarchyWindowItemCallback(int instanceID, Rect selectionRect)
        {
            if (FsmEditorSettings.DrawPlaymakerGizmoInHierarchy)
            {
                GameObject gameObject = EditorUtility.InstanceIDToObject(instanceID) as GameObject;
                if ((gameObject != null) && FsmEditorUtility.GameObjectHasFSM(gameObject))
                {
                    Rect position = new Rect((selectionRect.x + selectionRect.width) - 20f, selectionRect.y, 20f, 20f);
                    GUI.Box(position, FsmEditorStyles.TitleIcon, GUIStyle.none);
                }
            }
        }

        public void InitWindow(EditorWindow fsmEditorWindow)
        {
            this.window = fsmEditorWindow;
            this.window.title = "状态机编辑器";
            this.window.minSize = new Vector2(800f, 200f);
            this.window.autoRepaintOnSceneChange = true;
            this.window.wantsMouseMove = true;
        }

        public static void InstantiatePrefab()
        {
            if (SelectedFsmGameObject != null)
            {
                RegisterSceneUndo("Make Prefab Instance");
                GameObject obj2 = (GameObject) EditorUtility.InstantiatePrefab(SelectedFsmGameObject);
                UnityEditor.Selection.activeGameObject = obj2;
            }
        }

        public void OnDisable()
        {
            EditorApplication.playmodeStateChanged = (EditorApplication.CallbackFunction) Delegate.Remove(EditorApplication.playmodeStateChanged, this.playmodeDelegate);
            EditorApplication.hierarchyWindowItemOnGUI = (UnityEditor.EditorApplication.HierarchyWindowItemCallback) Delegate.Remove(EditorApplication.hierarchyWindowItemOnGUI, this.hiearchyItemCallback);
            FsmEditorUtility.DestroyLoadedTextures();
            Builder.OnDestroy();
            Resources.UnloadUnusedAssets();
            fsmComponentList.Clear();
            fsmList.Clear();
            instance = null;
        }

        public void OnEnable()
        {
            FsmEditorSettings.LoadSettings();
            RebuildFsmList();
            if (!Application.isPlaying && !this.playmodeChanged)
            {
                this.Reinitialize();
            }
            this.playmodeChanged = false;
            if (this.selectedFsmComponent != null)
            {
                SelectFsm(this.selectedFsmComponent.Fsm);
            }
            else
            {
                this.OnSelectionChange();
            }
            FsmErrorChecker.ClearErrors(true);
            FsmErrorChecker.CheckForErrors();
            FsmEditorUtility.BuildTemplateList();
            this.playmodeDelegate = new EditorApplication.CallbackFunction(this.PlaymodeChanged);
            EditorApplication.playmodeStateChanged = (EditorApplication.CallbackFunction) Delegate.Combine(EditorApplication.playmodeStateChanged, this.playmodeDelegate);
            this.hiearchyItemCallback = new UnityEditor.EditorApplication.HierarchyWindowItemCallback(this.HierarchyWindowItemCallback);
            EditorApplication.hierarchyWindowItemOnGUI = (UnityEditor.EditorApplication.HierarchyWindowItemCallback) Delegate.Combine(EditorApplication.hierarchyWindowItemOnGUI, this.hiearchyItemCallback);
            GameStateTracker.Update();
            currentScene = EditorApplication.currentScene;
        }

        public void OnFocus()
        {
            instance = this;
            RebuildFsmList();
            this.ResyncFsmSelection();
            CheckIsModifiedPrefabInstance();
            Repaint(false);
        }

        public void OnGUI()
        {
            if (!FsmEditorGUILayout.DoEditorDisabledGUI())
            {
                if (EditorApplication.isCompiling)
                {
                    GUI.enabled = false;
                }
                if (!FsmEditorStyles.IsInitialized())
                {
                    FsmEditorStyles.Init();
                }
                EventType type = Event.current.type;
                switch (type)
                {
                    case EventType.MouseUp:
                        this.mouseUp = true;
                        break;

                    case EventType.MouseDown:
                        this.mouseDown = true;
                        InspectorHasFocus = Event.current.mousePosition.x > (this.window.position.width - 350f);
                        break;
                }
                if ((SelectedFsm != null) && (Selection.ActiveFsmGameObject == null))
                {
                    SelectFsm((Fsm) null);
                }
                if (type == EventType.Repaint)
                {
                    this.repaint = false;
                }
                if (this.repaint)
                {
                    this.window.Repaint();
                    HandleUtility.Repaint();
                    this.repaint = false;
                }
                if (resetKeyboard)
                {
                    GUIUtility.keyboardControl = 0;
                    resetKeyboard = false;
                }
                if (((Event.current.type == EventType.KeyDown) && (GUIUtility.hotControl == 0)) && ((GUIUtility.keyboardControl == 0) && (Event.current.keyCode == KeyCode.Delete)))
                {
                    if (InspectorHasFocus && (Inspector.Mode == HutongGames.PlayMakerEditor.InspectorMode.StateInspector))
                    {
                        StateInspector.DeleteSelectedActions(true);
                    }
                    else
                    {
                        EditorCommands.DeleteMultiSelection();
                    }
                    GUIUtility.ExitGUI();
                }
                else
                {
                    this.toolbar.OnGUI();
                    float fixedHeight = EditorStyles.toolbar.fixedHeight;
                    this.inspector.OnGUI(new Rect(this.window.position.width - 350f, 0f, 350f, this.window.position.height));
                    this.graphView.OnGUI(new Rect(0f, fixedHeight, this.window.position.width - 350f, this.window.position.height - fixedHeight));
                }
            }
        }

        public void OnHierarchyChange()
        {
            RebuildFsmList();
            this.ResyncFsmSelection();
            if (!Application.isPlaying)
            {
                if (FsmEditorSettings.EnableRealtimeErrorChecker)
                {
                    FsmErrorChecker.CheckForErrors();
                }
                GlobalEventsWindow.ResetView();
            }
            GlobalVariablesWindow.ResetView();
            if (EditorApplication.currentScene != currentScene)
            {
                this.OnSceneChange();
            }
        }

        public void OnInspectorUpdate()
        {
            if (updateIsModifiedPrefabInstance > 0)
            {
                UpdateIsModifiedPrefabInstance();
            }
        }

        public void OnProjectChange()
        {
            FsmErrorChecker.ClearErrors(true);
            FsmEditorUtility.BuildActionsList();
            FsmEditorUtility.BuildScriptList();
            FsmEditorUtility.BuildTemplateList();
        }

        public void OnSceneChange()
        {
            if (FsmEditorSettings.AutoLoadPrefabs)
            {
                FsmEditorUtility.LoadUsedPrefabs();
            }
            RebuildFsmList();
            if (!Application.isPlaying)
            {
                this.Reinitialize();
            }
            currentScene = EditorApplication.currentScene;
        }

        public void OnSelectionChange()
        {
            bool needRepaint = false;
            GameObject go = UnityEditor.Selection.activeGameObject;
            if (go != null)
            {
                FsmUnit unit = go.GetComponent<FsmUnit>();
                if (unit != instance.selectedFsmUnit)
                {
                    SelectUnit(unit);
                    needRepaint = true;
                }

                FsmDevice dev = go.GetComponent<FsmDevice>();
                while (dev == null && go.transform.parent != null)
                {
                    go = go.transform.parent.gameObject;
                    dev = go.GetComponent<FsmDevice>();
                }
                if (dev != instance.selectedFsmDevice)
                {
                    SelectDevice(dev);
                    needRepaint = true;
                }
            }
            if (((!FsmEditorSettings.LockGraphView || (SelectedFsm == null)) && ((UnityEditor.Selection.activeGameObject != this.selectedGameObject) || (this.selectedGameObject == null))) && ((this.selectedFsmComponent == null) || (this.selectedFsmComponent.gameObject != UnityEditor.Selection.activeGameObject)))
            {
                PlayMakerFSM rfsm;
                FSMSelectedOnGameObjects.TryGetValue(UnityEditor.Selection.activeGameObject, out rfsm);
                SelectFsm((rfsm == null) ? FsmEditorUtility.FindFsmOnGameObject(UnityEditor.Selection.activeGameObject) : rfsm.Fsm);
                needRepaint = true;
            }
            if (needRepaint)
                Repaint(true);
        }

        public static void OpenAboutWindow()
        {
            sendWindowCommandEvent = "OpenAboutWindow";
        }

        public static void OpenActionWindow()
        {
            sendWindowCommandEvent = "OpenActionWindow";
        }

        public static void OpenErrorWindow()
        {
            sendWindowCommandEvent = "OpenErrorWindow";
        }

        public static void OpenEventManager()
        {
            Inspector.SetMode(HutongGames.PlayMakerEditor.InspectorMode.EventManager);
        }

        public static void OpenFsmLogWindow()
        {
            sendWindowCommandEvent = "OpenFsmLogWindow";
        }

        public static void OpenFsmSelectorWindow()
        {
            sendWindowCommandEvent = "OpenFsmSelectorWindow";
        }

        public static void OpenFsmTemplateWindow()
        {
            sendWindowCommandEvent = "OpenFsmTemplateWindow";
        }

        public static void OpenGlobalEventsWindow()
        {
            sendWindowCommandEvent = "OpenGlobalEventsWindow";
        }

        public static void OpenGlobalVariablesWindow()
        {
            sendWindowCommandEvent = "OpenGlobalVariablesWindow";
        }

        public static void OpenReportWindow()
        {
            sendWindowCommandEvent = "OpenReportWindow";
        }

        public static void OpenStateSelectorWindow()
        {
            sendWindowCommandEvent = "OpenStateSelectorWindow";
        }

        public static void OpenToolWindow()
        {
            sendWindowCommandEvent = "OpenToolWindow";
        }

        public static void OpenWelcomeWindow()
        {
            sendWindowCommandEvent = "OpenWelcomeWindow";
        }

        public static void Paste()
        {
            if (InspectorHasFocus && (Inspector.Mode == HutongGames.PlayMakerEditor.InspectorMode.StateInspector))
            {
                StateInspector.PasteActionsAfterSelected(true);
            }
            else
            {
                EditorCommands.PasteStates();
            }
        }

        private void PlaymodeChanged()
        {
            GameStateTracker.Update();
            this.playmodeChanged = true;
            if (GameStateTracker.StateChanged)
            {
                if (EditorApplication.isPaused && (GameStateTracker.PreviousState != GameState.Paused))
                {
                    DebugFlow.Start(SelectedFsm);
                    FsmTime.StartPlayerPause();
                }
                if (!EditorApplication.isPaused)
                {
                    DebugFlow.Stop();
                    FsmTime.EndPlayerPause();
                }
                if (!EditorApplication.isPlaying)
                {
                    Window.RemoveNotification();
                }
                this.ReinitializeAllFSMs();
                this.ResyncFsmSelection();
                FsmLog.LoggingEnabled = FsmEditorSettings.EnableLogging;
                FsmLog.MirrorDebugLog = FsmEditorSettings.MirrorDebugLog;
                FsmLog.EnableDebugFlow = FsmEditorSettings.EnableDebugFlow;
                if ((GameStateTracker.PreviousState == GameState.Stopped) || (GameStateTracker.CurrentState == GameState.Stopped))
                {
                    PlayMakerGlobals.ResetInstance();
                    PlayMakerGUI.ResetInstance();
                    ActionReport.ActionReportList.Clear();
                    FsmErrorChecker.ClearErrors(true);
                    GlobalVariablesWindow.ResetView();
                    FsmInspector.Init();
                    warnedAboutEditingWhileRunning = false;
                }
                RepaintAll();
            }
        }

        public static void RebuildFsmList()
        {
            fsmComponentList.Clear();
            PlayMakerGUI.ClearPreviewFsmList();
            fsmComponentList.AddRange(new List<PlayMakerFSM>((PlayMakerFSM[]) Resources.FindObjectsOfTypeAll(typeof(PlayMakerFSM))));
            fsmList.Clear();
            foreach (PlayMakerFSM rfsm in fsmComponentList)
            {
                if (rfsm.Fsm != null)
                {
                    rfsm.Fsm.Owner = rfsm;
                    foreach (FsmState state in rfsm.Fsm.States)
                    {
                        state.Fsm = rfsm.Fsm;
                    }
                    fsmList.Add(rfsm.Fsm);
                    PlayMakerGUI.AddPreviewFsm(rfsm);
                }
            }
            EditorApplication.RepaintHierarchyWindow();
        }

        public static void ReconnectToLastPrefab()
        {
            if (SelectedFsmGameObject != null)
            {
                EditorUtility.ReconnectToLastPrefab(SelectedFsmGameObject);
            }
        }

        internal static void RegisterActionEditUndo(string action)
        {
            if (SelectedFsm != null)
            {
                Undo.RegisterUndo(SelectedFsmComponent, "Edit Action : " + action);
            }
        }

        internal static void RegisterGlobalsUndo(string action)
        {
            Undo.RegisterUndo(PlayMakerGlobals.Instance, "playMaker : " + action);
        }

        internal static void RegisterSceneUndo(string action)
        {
            Undo.RegisterSceneUndo("playMaker : " + action);
        }

        internal static void RegisterUndo(string action)
        {
            if (SelectedFsm != null)
            {
                Undo.RegisterUndo(SelectedFsmComponent, "playMaker : " + action);
            }
        }

        internal static void RegisterUndo(UnityEngine.Object unityObject, string action)
        {
            if (unityObject != null)
            {
                Undo.RegisterUndo(unityObject, "playMaker : " + action);
            }
        }

        private void Reinitialize()
        {
            RebuildFsmList();
            this.ReinitializeAllFSMs();
            initialized = true;
            GlobalEventsWindow.ResetView();
            RepaintAll();
        }

        private void ReinitializeAllFSMs()
        {
            ActionReport.Start();
            RebuildFsmList();
            foreach (Fsm fsm in FsmList)
            {
                if (EditorApplication.isPlayingOrWillChangePlaymode)
                {
                    if (EditorUtility.GetPrefabType(fsm.GameObject) == PrefabType.Prefab)
                    {
                        fsm.Reinitialize();
                    }
                    else
                    {
                        fsm.InitData();
                    }
                }
                else
                {
                    fsm.Reinitialize();
                }
            }
            if (ActionReport.ActionReportList.Count > 0)
            {
                if (ActionReport.ErrorCount > 0)
                {
                    Debug.LogError("Some actions have changed since FSMs were saved! Please check the PlayMaker Console for errors...");
                    this.openReport = true;
                }
                else
                {
                    Debug.Log("Some actions have changed since FSMs were saved. All parameters have been updated successfully. Check the PlayMaker Console for details...");
                }
            }
        }

        public static void Repaint([Optional, DefaultParameterValue(false)] bool instant)
        {
            if (instance != null)
            {
                if (instant)
                {
                    if (Window != null)
                    {
                        Window.Repaint();
                    }
                }
                else
                {
                    instance.repaint = true;
                }
            }
        }

        public static void RepaintAll()
        {
            if (instance != null)
            {
                instance.repaintAll = true;
            }
        }

        private void ResetFsmViews()
        {
            FsmSelector.Refresh();
            this.graphView.ResetView();
            this.inspector.ResetView();
            RepaintAll();
        }

        public static void ResetKeyboard()
        {
            resetKeyboard = true;
        }

        public static void ResetToPrefabState()
        {
            if (SelectedFsmGameObject != null)
            {
                EditorUtility.ResetToPrefabState(SelectedFsm.Owner);
                CheckIsModifiedPrefabInstance();
                Inspector.ResetView();
                RepaintAll();
            }
        }

        private void ResyncFsmSelection()
        {
            if (this.selectedFsmComponent != null)
            {
                foreach (PlayMakerFSM rfsm in FsmComponentList)
                {
                    if (this.selectedFsmComponent == rfsm)
                    {
                        SelectFsm(rfsm.Fsm);
                    }
                }
            }
        }

        public static void SanityCheckEditor()
        {
            if (!FsmListContainsFsm(SelectedFsm))
            {
                SelectFsm((Fsm) null);
            }
            if ((SelectedFsm != null) && !FsmContainsState(SelectedFsm, SelectedState))
            {
                Selection.SelectState(null, false, false);
            }
            HutongGames.PlayMakerEditor.StateInspector.SanityCheckActionSelection();
        }

        private static void SanityCheckFsm(Fsm fsm)
        {
            List<FsmEvent> fsmEventList = new List<FsmEvent>();
            foreach (FsmEvent event2 in fsm.ExposedEvents)
            {
                if (FsmEvent.EventListContainsEvent(new List<FsmEvent>(fsm.Events), event2.Name) && !FsmEvent.EventListContainsEvent(fsmEventList, event2.Name))
                {
                    fsmEventList.Add(event2);
                }
            }
            fsm.ExposedEvents = fsmEventList;
        }

        public static void SaveActions()
        {
            SaveActions(SelectedFsm);
        }

        public static void SaveActions(Fsm fsm)
        {
            if (fsm != null)
            {
                foreach (FsmState state in fsm.States)
                {
                    state.SaveActions();
                }
                SetFsmDirty(fsm, true, false);
            }
        }

        public static void SaveGlobals()
        {
            if (!Application.isPlaying)
            {
                if (!AssetDatabase.Contains(PlayMakerGlobals.Instance))
                {
                    string path = Path.Combine(Application.dataPath, "PlayMaker/Resources/");
                    if (!Directory.Exists(path))
                    {
                        EditorUtility.DisplayDialog("Playmaker", "PlayMakerGlobals asset created:\n\nAssets/PlayMaker/Resources/PlayMakerGlobals.asset\n\nNOTE: You can move this file to another Resources folder if desired.", "OK");
                        Directory.CreateDirectory(path);
                    }
                    AssetDatabase.CreateAsset(PlayMakerGlobals.Instance, "Assets/PlayMaker/Resources/PlayMakerGlobals.asset");
                    AssetDatabase.Refresh();
                }
                else
                {
                    EditorUtility.SetDirty(PlayMakerGlobals.Instance);
                }
            }
        }

        public static FsmStateAction SelectAction(FsmStateAction action, [Optional, DefaultParameterValue(true)] bool autoScroll)
        {
            if (instance == null)
            {
                return null;
            }
            instance.stateInspector.SelectAction(action, autoScroll);
            return action;
        }

        public static FsmStateAction SelectAction(FsmState state, int actionIndex, [Optional, DefaultParameterValue(true)] bool autoScroll)
        {
            if (((state == null) || (actionIndex < 0)) || (actionIndex >= state.Actions.Length))
            {
                return null;
            }
            FsmStateAction action = state.Actions[actionIndex];
            return SelectAction(action, autoScroll);
        }

        public static void SelectAll()
        {
            if (InspectorHasFocus && (Inspector.Mode == HutongGames.PlayMakerEditor.InspectorMode.StateInspector))
            {
                HutongGames.PlayMakerEditor.StateInspector.SelectAllActions();
            }
            else
            {
                EditorCommands.SelectAll();
            }
        }

        public static bool SelectedFsmIsPrefab()
        {
            return FsmEditorUtility.IsPrefab(SelectedFsm);
        }

        public static void SelectDevice(FsmDevice device)
        {
            instance.selectedFsmDevice = device;
        }

        public static void SelectUnit(FsmUnit unit)
        {
            instance.selectedFsmUnit = unit;
        }

        public static void SelectFsm(Fsm fsm)
        {
            if (instance != null)
            {
                if (SelectedFsm != null)
                {
                    SelectedFsm.EditState = null;
                }
                instance.selectedFsmComponent = (fsm == null) ? null : ((PlayMakerFSM) fsm.Owner);
                instance.fsmSelection = FsmSelection.GetFsmSelection(fsm);
                if (SelectedFsm != null)
                {
                    FSMSelectedOnGameObjects.Remove(SelectedFsmGameObject);
                    FSMSelectedOnGameObjects.Add(SelectedFsmGameObject, (PlayMakerFSM) SelectedFsm.Owner);
                    instance.selectedFsmComponent = (PlayMakerFSM) SelectedFsm.Owner;
                    instance.selectedGameObject = SelectedFsm.GameObject;
                    if (FsmEditorSettings.AutoAddPlayMakerGUI)
                    {
                        AutoAddPlayMakerGUI();
                    }
                    if (SelectedState != null)
                    {
                        SelectedFsm.EditState = SelectedState;
                    }
                    SelectedFsm.Init(SelectedFsmComponent);
                    FsmInspector.Init();
                    SanityCheckFsm(SelectedFsm);
                    FsmErrorChecker.CheckForErrors();
                    if (instance.recentlySelectedList.Contains(SelectedFsm))
                    {
                        instance.recentlySelectedList.Remove(SelectedFsm);
                    }
                    instance.recentlySelectedList.Insert(0, SelectedFsm);
                }
                else
                {
                    instance.selectedGameObject = null;
                    instance.selectedFsmComponent = null;
                }
                if (FsmEditorSettings.AutoSelectGameObject && !FsmEditorSettings.LockGraphView)
                {
                    Selection.SelectActiveFsmGameObject();
                }
                if ((Application.isPlaying && FsmEditorSettings.SelectStateOnActivated) && (fsm != null))
                {
                    SelectState(fsm.ActiveState, true);
                }
                DebugFlow.SyncFsmLog(fsm);
                Fsm.StepToStateChange = false;
                instance.ResetFsmViews();
                Repaint(true);
                RepaintAll();
            }
        }

        public static void SelectFsm(object userdata)
        {
            Fsm fsm = userdata as Fsm;
            SelectFsm(fsm);
        }

        public static void SelectFsmGameObject()
        {
            if (SelectedFsmGameObject != null)
            {
                UnityEditor.Selection.activeGameObject = SelectedFsmGameObject;
                EditorGUIUtility.PingObject(SelectedFsmGameObject);
            }
        }

        public static void SelectPrefabParent()
        {
            if (SelectedFsmGameObject != null)
            {
                GameObject prefabParent = (GameObject) EditorUtility.GetPrefabParent(SelectedFsmGameObject);
                UnityEditor.Selection.activeGameObject = prefabParent;
            }
        }

        public static FsmState SelectState(FsmState state, bool frameState)
        {
            if (instance == null)
            {
                return null;
            }
            if (state != SelectedState)
            {
                state = Selection.SelectState(state, false, false);
            }
            if ((FsmEditorSettings.FrameSelectedState || frameState) && GraphView.IsStateOffscreen(state))
            {
                GraphView.FrameState(state);
            }
            if (!Application.isPlaying)
            {
                Inspector.SetMode(HutongGames.PlayMakerEditor.InspectorMode.StateInspector);
            }
            return state;
        }

        public static FsmState SelectStateByName(string stateName)
        {
            return SelectState(SelectedFsm.GetState(stateName), true);
        }

        public static void SelectStateFromMenu(object userdata)
        {
            SelectStateByName(userdata as string);
            GraphView.FrameState(Selection.ActiveState);
        }

        public static void SelectTemplate(FsmTemplate template)
        {
            instance.selectedTemplate = template;
        }

        public static void SetFsmDirty(bool errorCheck, [Optional, DefaultParameterValue(false)] bool checkAll)
        {
            if (SelectedFsm != null)
            {
                SetFsmDirty(SelectedFsm, errorCheck, checkAll);
            }
        }

        public static void SetFsmDirty(Fsm fsm, bool errorCheck, [Optional, DefaultParameterValue(false)] bool checkAll)
        {
            if (fsm != null)
            {
                EditorUtility.SetDirty(fsm.Owner);
                if (errorCheck && FsmEditorSettings.EnableRealtimeErrorChecker)
                {
                    if (checkAll)
                    {
                        FsmErrorChecker.CheckForErrors();
                    }
                    else
                    {
                        FsmErrorChecker.CheckFsmForErrors(fsm);
                    }
                }
                RepaintAll();
                if (((GameStateTracker.CurrentState == GameState.Running) && !warnedAboutEditingWhileRunning) && FsmEditorSettings.ShowEditWhileRunningWarning)
                {
                    Window.ShowNotification(FsmEditorUtility.IsPrefab(SelectedFsm) ? new GUIContent("You are editing a Prefab while the game is playing.\nChanges WILL persist after you stop playing!") : new GUIContent("You are editing the FSM while the game is playing.\nChanges will be lost when you stop playing!"));
                    warnedAboutEditingWhileRunning = true;
                }
                CheckIsModifiedPrefabInstance();
            }
        }

        public static bool StateContainsTransition(FsmState state, FsmTransition transition)
        {
            if ((state != null) && (transition != null))
            {
                foreach (FsmTransition transition2 in state.Transitions)
                {
                    if (transition2 == transition)
                    {
                        return true;
                    }
                }
            }
            return false;
        }

        public static void UndoRedoPerformed()
        {
            SetFsmDirty(true, false);
            RebuildFsmList();
            SanityCheckEditor();
            Inspector.ResetView();
            GlobalEventsWindow.ResetView();
            if (SelectedFsm != null)
            {
                SelectedFsm.Reinitialize();
            }
            if (FsmEditorSettings.EnableRealtimeErrorChecker)
            {
                FsmErrorChecker.CheckForErrors();
            }
            CheckIsModifiedPrefabInstance();
            Window.Repaint();
            RepaintAll();
        }

        public void Update()
        {
            if (!Application.isPlaying || !FsmEditorSettings.DisableEditorWhenPlaying)
            {
                if (!initialized)
                {
                    this.Reinitialize();
                }
                if (!string.IsNullOrEmpty(sendWindowCommandEvent))
                {
                    Window.SendEvent(EditorGUIUtility.CommandEvent(sendWindowCommandEvent));
                    sendWindowCommandEvent = "";
                }
                if (this.openReport)
                {
                    OpenReportWindow();
                    this.openReport = false;
                }
                if (FsmEditorSettings.SelectFSMInGameView)
                {
                    if ((!FsmEditorSettings.LockGraphView || (SelectedFsm == null)) && ((Fsm.LastClickedObject != null) && (SelectedFsmGameObject != Fsm.LastClickedObject)))
                    {
                        UnityEditor.Selection.activeGameObject = Fsm.LastClickedObject;
                        EditorGUIUtility.PingObject(SelectedFsmGameObject);
                    }
                    Fsm.LastClickedObject = null;
                }
                if (currentScene != EditorApplication.currentScene)
                {
                    this.OnSceneChange();
                }
                if (this.repaintAll)
                {
                    this.window.SendEvent(EditorGUIUtility.CommandEvent("RepaintAll"));
                    this.repaintAll = false;
                    this.repaint = false;
                }
                if ((SelectedState != null) && !Application.isPlaying)
                {
                    CheckReloadActions(SelectedState);
                }
                this.graphView.Update();
                this.inspector.Update();
                this.debugger.Update();
                this.mouseUp = false;
                this.mouseDown = false;
                FsmErrorChecker.Update();
                DragAndDropManager.Update();
            }
        }

        private static void UpdateIsModifiedPrefabInstance()
        {
            updateIsModifiedPrefabInstance--;
            if (updateIsModifiedPrefabInstance == 0)
            {
                foreach (Fsm fsm in FsmList)
                {
                    fsm.IsModifiedPrefabInstance = FsmEditorUtility.IsModifiedPrefabInstance(fsm);
                }
                RepaintAll();
            }
        }

        internal static HutongGames.PlayMakerEditor.ActionEditor ActionEditor
        {
            get
            {
                return instance.actionEditor;
            }
        }

        public static FsmBuilder Builder
        {
            get
            {
                if (instance != null)
                {
                    return instance.builder;
                }
                return null;
            }
        }

        internal static FsmDebugger Debugger
        {
            get
            {
                return instance.debugger;
            }
        }

        internal static FsmEventManager EventManager
        {
            get
            {
                return instance.eventManager;
            }
        }

        public static List<PlayMakerFSM> FsmComponentList
        {
            get
            {
                return fsmComponentList;
            }
        }

        public static List<Fsm> FsmList
        {
            get
            {
                return fsmList;
            }
        }

        internal static FsmGraphView GraphView
        {
            get
            {
                return instance.graphView;
            }
        }

        internal static InspectorPanel Inspector
        {
            get
            {
                return instance.inspector;
            }
        }

        public static bool InspectorHasFocus
        {
            [CompilerGenerated]
            get
            {
                return InspectorHasFocus__BackingField;
            }
            [CompilerGenerated]
            set
            {
                InspectorHasFocus__BackingField = value;
            }
        }

        public static FsmEditor Instance
        {
            get
            {
                return instance;
            }
        }

        public static bool MouseDown
        {
            get
            {
                return instance.mouseDown;
            }
        }

        public static bool MouseUp
        {
            get
            {
                return instance.mouseUp;
            }
        }

        public static bool NeedRepaint
        {
            get
            {
                if (!instance.repaint)
                {
                    return instance.repaintAll;
                }
                return true;
            }
        }

        public static List<Fsm> RecentlySelectedList
        {
            get
            {
                if (instance == null)
                {
                    return null;
                }
                return instance.recentlySelectedList;
            }
        }

        public static Fsm SelectedFsm
        {
            get
            {
                if ((instance != null) && (instance.selectedFsmComponent != null))
                {
                    return instance.selectedFsmComponent.Fsm;
                }
                return null;
            }
        }

        public static FsmDevice SelectedDevice
        {
            get
            {
                if ((instance != null) && (instance.selectedFsmDevice != null))
                {
                    return instance.selectedFsmDevice;
                }
                return null;
            }
        }

        public static FsmUnit SelectedUnit
        {
            get
            {
                if ((instance != null) && (instance.selectedFsmUnit != null))
                {
                    return instance.selectedFsmUnit;
                }
                return null;
            }
        }

        public static PlayMakerFSM SelectedFsmComponent
        {
            get
            {
                if (instance == null)
                {
                    return null;
                }
                return instance.selectedFsmComponent;
            }
        }

        public static GameObject SelectedFsmGameObject
        {
            get
            {
                if (instance != null)
                {
                    return Selection.ActiveFsmGameObject;
                }
                return null;
            }
        }

        public static FsmState SelectedState
        {
            get
            {
                if (instance != null)
                {
                    return Selection.ActiveState;
                }
                return null;
            }
        }

        public static string SelectedStateName
        {
            get
            {
                if (SelectedState != null)
                {
                    return SelectedState.Name;
                }
                return "";
            }
        }

        public static List<FsmState> SelectedStates
        {
            get
            {
                if (instance != null)
                {
                    return Selection.States;
                }
                return null;
            }
        }

        public static FsmTemplate SelectedTemplate
        {
            get
            {
                if (instance != null)
                {
                    return instance.selectedTemplate;
                }
                return null;
            }
        }

        public static FsmTransition SelectedTransition
        {
            get
            {
                if (instance != null)
                {
                    return Selection.ActiveTransition;
                }
                return null;
            }
        }

        internal static FsmSelection Selection
        {
            get
            {
                if (instance == null)
                {
                    return null;
                }
                return (instance.fsmSelection ?? (instance.fsmSelection = FsmSelection.GetFsmSelection(null)));
            }
        }

        public static List<Fsm> SortedFsmList
        {
            get
            {
                List<Fsm> list = new List<Fsm>(FsmList);
                list.Sort();
                return list;
            }
        }

        internal static HutongGames.PlayMakerEditor.StateInspector StateInspector
        {
            get
            {
                return instance.stateInspector;
            }
        }

        internal static MainToolbar Toolbar
        {
            get
            {
                return instance.toolbar;
            }
        }

        internal static HutongGames.PlayMakerEditor.VariableManager VariableManager
        {
            get
            {
                return instance.variableManager;
            }
        }

        public static EditorWindow Window
        {
            get
            {
                if (instance != null)
                {
                    return instance.window;
                }
                return null;
            }
        }
    }
}

